﻿//lock 用于读一个引用类型进行加锁，同一时刻内只有一个线程能够访问此对象。lock 是语法糖，是通过 Monitor 来实现的。
//定义一个锁对象

Object LockObject = new();
int sum = 0;

//Thread thread1 = new Thread(sum1);
//thread1.Start();
//Thread thread2 = new Thread(sum2);
//thread2.Start();
//while (true)
//{
//    Console.WriteLine($"{DateTime.Now.ToString()}:" + sum);
//    Thread.Sleep(TimeSpan.FromSeconds(1));
//}
//string a = "123";
//lock (a)
//{
//}

//以上代码通过sharplab.io编译后为
//string text = "123";
//string obj = text;
//bool lockTaken = false;
//try
//{
//    Monitor.Enter(obj, ref lockTaken);
//}
//finally
//{
//    if (lockTaken)
//    {
//        Monitor.Exit(obj);
//    }
//}

//lock关键字是一种语法糖，基于Monitor类实现
object obj = new object();
bool acquiredLock = false;
new Thread(Test1).Start();
Thread.Sleep(1000);
new Thread(Test2).Start();

void sum1()
{
    sum = 0;
    lock (LockObject)
    {
        for (int i = 0; i < 10; i++)
        {
            sum += i;
            Console.WriteLine("sum1");
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }
    }
}

void sum2()
{
    sum = 0;
    lock (LockObject)
    {
        for (int i = 0; i < 10; i++)
        {
            sum += i;
            Console.WriteLine("sum2");
            Thread.Sleep(TimeSpan.FromSeconds(2));
        }
    }
}

void Test1()
{
    try
    {
        Monitor.Enter(obj, ref acquiredLock);
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("Test1正在锁定资源");
            Thread.Sleep(1000);
        }
    }
    catch { }
    finally
    {
        if (acquiredLock)
            Monitor.Exit(obj);
        Console.WriteLine("Test1已经释放资源");
    }
}
void Test2()
{
    bool isGetLock = false;
    Monitor.Enter(obj);
    try
    {
        Monitor.Enter(obj, ref acquiredLock);
        for (int i = 0; i < 10; i++)
        {
            Console.WriteLine("Test2正在锁定资源");
            Thread.Sleep(1000);
        }
    }
    catch { }
    finally
    {
        if (acquiredLock)
            Monitor.Exit(obj);
        Console.WriteLine("Test2已经释放资源");
    }
}